home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume17 / zoo2 / part09 < prev    next >
Encoding:
Internet Message Format  |  1989-02-01  |  42.5 KB

  1. Subject:  v17i072:  Zoo archive program, Part09/10
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: Rahul Dhesi <bsu-cs!dhesi@iuvax.cs.indiana.edu>
  6. Posting-number: Volume 17, Issue 72
  7. Archive-name: zoo2/part09
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 9 (of 10)."
  16. # Wrapped by rsalz@papaya.bbn.com on Thu Feb  2 18:04:05 1989
  17. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  18. if test -f 'zooio.h' -a "${1}" != "-c" ; then 
  19.   echo shar: Will not clobber existing file \"'zooio.h'\"
  20. else
  21. echo shar: Extracting \"'zooio.h'\" \(2074 characters\)
  22. sed "s/^X//" >'zooio.h' <<'END_OF_FILE'
  23. X/* @(#) zooio.h 2.7 88/01/27 19:39:24 */
  24. X
  25. X/*
  26. XDeclarations for portable I/O
  27. X
  28. XThe contents of this file are hereby placed in the public domain.
  29. X
  30. X                                            -- Rahul Dhesi 1988/01/24
  31. X*/
  32. X#ifndef    OK_STDIO
  33. X#include <stdio.h>
  34. X#define    OK_STDIO
  35. X#endif
  36. X
  37. X#ifndef PARMS
  38. X#ifdef LINT_ARGS
  39. X#define    PARMS(x)        x
  40. X#else
  41. X#define    PARMS(x)        ()
  42. X#endif
  43. X#endif
  44. X
  45. X/*
  46. XIn theory, all I/O using buffered files could be replaced with unbuffered
  47. XI/O simply by changing the following definitions.  This has not been tried
  48. Xout yet, and there may be some remaining holes in the scheme.  On systems
  49. Xwith limited memory, it might prove necessary to use unbuffered I/O
  50. Xonly.
  51. X*/
  52. Xtypedef FILE *ZOOFILE;
  53. X#define NOFILE        ((ZOOFILE) 0)
  54. X#define NULLFILE    ((ZOOFILE) -1)        /* or any unique value */
  55. X#define STDOUT        stdout
  56. X
  57. X#ifdef FILTER
  58. X#define STDIN        stdin
  59. X#endif
  60. X
  61. X#ifdef IO_MACROS
  62. X#define zooread(file, buffer, count)        fread (buffer, 1, count, file)
  63. X#define zoowrite(file, buffer, count) \
  64. X    (file == NULLFILE ? count : fwrite (buffer, 1, count, file))
  65. X#define zooseek(file, offset, whence)        fseek (file, offset, whence)
  66. X#define zootell(file)                            ftell (file)
  67. X#else
  68. Xint zooread PARMS((ZOOFILE, char *, int));
  69. Xint zoowrite PARMS((ZOOFILE, char *, int));
  70. Xlong zooseek PARMS((ZOOFILE, long, int));
  71. Xlong zootell PARMS((ZOOFILE));
  72. X#endif /* IO_MACROS */
  73. X
  74. XZOOFILE zooopen PARMS((char *, char *));
  75. XZOOFILE zoocreate PARMS((char *));
  76. Xint zooclose PARMS((ZOOFILE));
  77. Xint zootrunc PARMS((ZOOFILE));
  78. X
  79. X#ifdef LINT_ARGS
  80. Xchar *choosefname (struct direntry *);
  81. Xchar *fullpath (struct direntry *);
  82. Xint frd_zooh (struct zoo_header *, ZOOFILE);
  83. Xint frd_dir (struct direntry *, ZOOFILE);
  84. Xint fwr_dir (struct direntry *, ZOOFILE);
  85. Xint fwr_zooh (struct zoo_header *, ZOOFILE);
  86. Xint readdir (struct direntry *, ZOOFILE, int);
  87. Xvoid rwheader (struct zoo_header *, ZOOFILE, int);
  88. Xvoid newdir (struct direntry *);
  89. Xvoid writedir (struct direntry *, ZOOFILE);
  90. X#else
  91. Xchar *choosefname ();
  92. Xchar *fullpath ();
  93. Xint frd_zooh ();
  94. Xint frd_dir ();
  95. Xint fwr_dir ();
  96. Xint fwr_zooh ();
  97. Xint readdir ();
  98. Xvoid rwheader ();
  99. Xvoid newdir ();
  100. Xvoid writedir ();
  101. X#endif
  102. END_OF_FILE
  103. if test 2074 -ne `wc -c <'zooio.h'`; then
  104.     echo shar: \"'zooio.h'\" unpacked with wrong size!
  105. fi
  106. # end of 'zooio.h'
  107. fi
  108. if test -f 'zoomem.h' -a "${1}" != "-c" ; then 
  109.   echo shar: Will not clobber existing file \"'zoomem.h'\"
  110. else
  111. echo shar: Extracting \"'zoomem.h'\" \(2456 characters\)
  112. sed "s/^X//" >'zoomem.h' <<'END_OF_FILE'
  113. X/* @(#) zoomem.h 2.1 87/12/25 12:26:18 */
  114. X
  115. X/*
  116. XThe contents of this file are hereby released to the public domain.
  117. X
  118. X                           -- Rahul Dhesi 1986/11/14
  119. X
  120. XDefines parameters used for memory allocation.  
  121. X
  122. X   Xenix notes:  Under Xenix release 3.0 on an Intel 310 machine with an
  123. X   80286 cpu, memory is very tight when the small memory model is used. 
  124. X   Ooz won't fit if the buffers are 2 K for input and 6 K for output.  
  125. X   It does fit if both input and output buffers are 1 K each.  Under
  126. X   the large memory model there is no problem.  Zoo requires the large
  127. X   memory model.
  128. X
  129. X   AT&T 3B2:  There seem to be no problem at all.  Buffers can always
  130. X   be 8192 each.
  131. X*/
  132. X
  133. X#ifdef OOZ
  134. X#define  IN_BUF_SIZE       8192
  135. X#define  OUT_BUF_SIZE      8192
  136. X#else
  137. X#define  IN_BUF_SIZE       8192
  138. X#define  OUT_BUF_SIZE      8192
  139. X#endif
  140. X
  141. X#define  MEM_BLOCK_SIZE    (IN_BUF_SIZE + OUT_BUF_SIZE)
  142. X
  143. X/* 
  144. XLIST_SIZE is the size of the list built by Zoo to hold all filenames
  145. Xencountered in an archive.  This is used to know when to replace an
  146. Xalready existing file.  The date and time stored with the filename is
  147. Xused in comparisons when an archive update has been requested.  To 
  148. Xadd a file to an archive, the archive must not already have more than
  149. XLIST_SIZE files in it.
  150. X
  151. XZOOCOUNT is the number of archive names that may be matched by the
  152. Xarchive filespec specified for a list.
  153. X
  154. XMAXADD is the number of filenames that may be added to an archive
  155. Xat one go.  The total number of files that an archive may contain
  156. Xis not determined by MAXADD but is determined by LIST_SIZE.
  157. X
  158. XIf USE_MALLOC is defined it tells the memory allocation routine 
  159. Xemalloc() not to bother with maintaining its own memory blocks but just to 
  160. Xpass on requests to the library function malloc().  If USE_MALLOC is not 
  161. Xdefined, emalloc() does its own memory management to save overhead on a 
  162. Xmachine with limited memory.
  163. X*/
  164. X
  165. X#ifdef   SMALL_MEM
  166. X#define  LIST_SIZE  (200)
  167. X#define  ZOOCOUNT   (30)
  168. X#define  MAXADD     (100)
  169. X#define  USE_MALLOC
  170. X#endif
  171. X
  172. X#ifdef   MED_MEM
  173. X#define  LIST_SIZE  (400)
  174. X#define  ZOOCOUNT   (50)
  175. X#define  MAXADD     (200)
  176. X#define  USE_MALLOC
  177. X#endif
  178. X
  179. X#ifdef   BIG_MEM
  180. X#define  LIST_SIZE  (4000)
  181. X#define  ZOOCOUNT   (400)
  182. X#define  MAXADD     (4000)
  183. X#define  USE_MALLOC
  184. X#endif
  185. X
  186. X/* Customizable sizes */
  187. X#ifdef   SPEC_MEM
  188. X#define  LIST_SIZE   (600)
  189. X#define  ZOOCOUNT    (100)
  190. X#define  MAXADD      (400)
  191. X#endif
  192. X
  193. Xextern char *out_buf_adr;              /* global I/O buffer */
  194. END_OF_FILE
  195. if test 2456 -ne `wc -c <'zoomem.h'`; then
  196.     echo shar: \"'zoomem.h'\" unpacked with wrong size!
  197. fi
  198. # end of 'zoomem.h'
  199. fi
  200. if test -f 'zooadd.c' -a "${1}" != "-c" ; then 
  201.   echo shar: Will not clobber existing file \"'zooadd.c'\"
  202. else
  203. echo shar: Extracting \"'zooadd.c'\" \(25720 characters\)
  204. sed "s/^X//" >'zooadd.c' <<'END_OF_FILE'
  205. X#ifndef LINT
  206. X/* @(#) zooadd.c 2.34 88/08/15 10:53:11 */
  207. Xstatic char sccsid[]="@(#) zooadd.c 2.34 88/08/15 10:53:11";
  208. X#endif /* LINT */
  209. X
  210. X/*
  211. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  212. X(C) Copyright 1988 Rahul Dhesi -- All rights reserved
  213. X*/
  214. X#include "options.h"
  215. X/* Adds files specified in parameter-list to archive zoo_path. */
  216. X
  217. X#define LONGEST    20                    /* assumed length of longest filename */
  218. X#include "zoomem.h"             /* to define MAXADD */
  219. X#include "zoo.h"
  220. X#include "zooio.h"
  221. X#include "various.h"
  222. X#include "parse.h"
  223. X#include "debug.h"
  224. X
  225. X#include "portable.h"
  226. X
  227. X#include "zoofns.h"
  228. X#include "errors.i"
  229. Xextern int break_hit;
  230. Xextern int quiet;
  231. X
  232. X#ifdef LINT_ARGS
  233. Xvoid show_comment (struct direntry *, ZOOFILE, int, char *);
  234. Xvoid dosname (char *, char *);
  235. Xvoid modpath (char *);
  236. Xvoid opts_add (char *, int *, int *, int *, int *, int *, int *,
  237. X               int *, int *, int *, int *, int *, int *);
  238. Xint ver_too_high (struct zoo_header *);
  239. Xget_comment (struct direntry *, ZOOFILE, char *);
  240. Xvoid copyfields (struct direntry *, struct tiny_header *);
  241. Xvoid storefname (struct direntry *, char *, int);
  242. Xchar *choosefname (struct direntry *);
  243. X#else
  244. Xvoid show_comment ();
  245. Xvoid dosname ();
  246. Xvoid modpath ();
  247. Xvoid opts_add ();
  248. Xint ver_too_high ();
  249. Xget_comment ();
  250. Xvoid copyfields ();
  251. Xvoid storefname ();
  252. Xchar *choosefname ();
  253. X#endif
  254. X
  255. Xextern struct zoo_header zoo_header;
  256. X
  257. Xextern char file_leader[];
  258. Xextern unsigned int crccode;
  259. X
  260. Xvoid zooadd(zoo_path, argc, argv, option)
  261. Xchar *zoo_path;      /* pathname of zoo archive to add to */
  262. Xint argc;            /* how many filespecs supplied */
  263. Xchar **argv;         /* array of pointers to filespecs */
  264. Xchar *option;        /* option string */
  265. X{
  266. Xchar *whichname;                          /* which name to show user */
  267. Xchar *flist[MAXADD];                      /* list of ptrs to input fnames */
  268. Xint fptr;                                 /* will point to within flist */
  269. XZOOFILE this_file;                        /* file to add */
  270. Xchar zoo_fname[LFNAMESIZE];               /* basename of archive itself */
  271. Xchar zoo_bak[LFNAMESIZE];                 /* name of archive's backup */
  272. Xchar this_fname[LFNAMESIZE];              /* just filename of file to add */
  273. Xchar latest_name[LFNAMESIZE];             /* latest name in archive */
  274. Xlong last_old = 0L;                       /* last direntry in old chain */
  275. XZOOFILE zoo_file;                         /* stream for open archive */
  276. Xchar *this_path;                          /* pathname of file to add */
  277. X
  278. X#ifdef NOENUM
  279. X#define NEW_ZOO 1
  280. X#define OLD_ZOO 2
  281. Xint zoo_status;
  282. X#else
  283. Xenum {NEW_ZOO, OLD_ZOO} zoo_status;       /* newly created or not */
  284. X#endif
  285. X
  286. Xlong this_dir_offset;                     /* pointers to within archive */
  287. Xlong save_position;                       /* pointer to within archive */
  288. Xlong prev_pos;                            /* posn of prev file of same name */
  289. Xstruct direntry direntry;                 /* directory entry */
  290. Xstruct direntry dir2entry;                /* spare */
  291. Xint status;                               /* error status */
  292. Xint success;                              /* successful addition of file? */
  293. Xint addcount = 0;                         /* number added */
  294. Xint update=0;                             /* only files already in archive */
  295. Xint suppress=0;                           /* suppress compression */
  296. Xint new=0;                                /* add only files not in archive */
  297. Xint zootime = 0;                          /* just set archive time */
  298. Xint add_comment = 0;                      /* add comment */
  299. Xint pack = 0;                             /* pack after adding */
  300. Xint need_dir = 1;                         /* store directories too */
  301. Xint delcount = 0;                         /* count of deleted entries */
  302. Xint exit_status = 0;                      /* exit status to set */
  303. X
  304. Xunsigned int latest_date = 0;             /* to set time on archive itself */
  305. Xunsigned int latest_time = 0;             /* .. same */
  306. Xint move = 0;                             /* delete after adding to archive */
  307. Xint longest;                              /* length of longest pathname added */
  308. Xint firstfile = 1;                        /* first file being added? */
  309. Xint z_fmt = 0;                            /* look for Z format files? */
  310. Xint inargs = 0;                                    /* read filenames from stdin? */
  311. X
  312. X#ifndef PORTABLE
  313. Xstruct tiny_header tiny_header;           /* for Z format archives */
  314. X#endif
  315. X
  316. Xunsigned this_version_no;                            /* version no. of old file */
  317. Xunsigned  high_vflag;                                /* version flag of old file */
  318. Xunsigned high_version_no;                            /* highest version no of this file */
  319. Xlong high_pos;                                        /* offset of file w/highest ver no */
  320. Xunsigned int fgens;                                /* gens. to preserve -- file */
  321. Xunsigned int zgens;                                /* gens. to preserve -- archive */
  322. Xlong oldcmtpos;                                    /* to save old comment */
  323. Xunsigned int oldcmtsiz;                            /* to save old comment */
  324. Xint genson = 0;                                    /* whether to turn generations on */
  325. X
  326. X/* on entry option points to first letter */
  327. X
  328. Xopts_add (option, &zootime, &quiet, &suppress, &move, &new, &pack,
  329. X          &update, &add_comment, &z_fmt, &need_dir, &inargs, &genson);
  330. X
  331. X/* POSSIBLE RACE CONDITION BETWEEN TESTING EXISTENCE AND CREATING FILE */
  332. Xif (exists (zoo_path)) {
  333. X    zoo_file = zooopen (zoo_path, Z_RDWR);
  334. X   zoo_status = OLD_ZOO;
  335. X} else {
  336. X   if (!zootime)
  337. X        zoo_file = zoocreate (zoo_path);
  338. X   else
  339. X      zoo_file = NOFILE;     /* don't create if just setting time */
  340. X   zoo_status = NEW_ZOO;
  341. X}
  342. X
  343. Xif (zoo_file == NOFILE)
  344. X   prterror ('f', could_not_open, zoo_path);
  345. X
  346. Xbasename(zoo_path, zoo_fname);      /* get basename of archive */
  347. Xrootname (zoo_path, zoo_bak);       /* name without extension */
  348. Xstrcat (zoo_bak, BACKUP_EXT);       /* name of backup of this archive */
  349. X
  350. X/* Now we prepare the archive for adding one or more files.  If the archive
  351. Xhas just been created, we write the archive header */
  352. X
  353. Xaddfname ("",0L,0,0,0,0); /* initialize table of files already in archive */
  354. Xif (zoo_status == NEW_ZOO) {                 /* newly-created archive */
  355. X    if (genson)                                            /* if no generations needed */
  356. X        zoo_header.vdata = (VFL_ON|GEN_DEFAULT); /* generations on */
  357. X   fwr_zooh (&zoo_header, zoo_file);
  358. X    zgens = GEN_DEFAULT;
  359. X   zooseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */
  360. X} else {
  361. X   /* read header and rewrite with updated version numbers, preserving
  362. X       header type */
  363. X   rwheader (&zoo_header, zoo_file, 1);
  364. X    zgens = zoo_header.vdata & VFL_GEN;            /* get archive generations */
  365. X   /* initialize latest_name to null string */
  366. X    /* NOTE:  latest_name is not currently used for anything, but
  367. X        may be used in the future for inserting files into the
  368. X        archive in alphabetic order. */
  369. X   *latest_name = '\0';
  370. X
  371. X   /* Skip existing files but add them to a list.  The variable last_old 
  372. X   gets the tail of the old chain of directory entries */
  373. X   skip_files (zoo_file, &latest_date, &latest_time, &delcount, 
  374. X               latest_name, &last_old);
  375. X}
  376. X/* The file pointer is now positioned correctly to add a file to archive, 
  377. Xunless the null directory entry is too short.  This will be fixed below. */
  378. X
  379. X/* If we are just setting time, do it and run. */
  380. Xif (zootime) {
  381. X#ifdef NIXTIME
  382. X   zooclose (zoo_file);
  383. X   setutime (zoo_path, latest_date, latest_time);
  384. X#else
  385. X   settime (zoo_file, latest_date, latest_time);
  386. X   zooclose (zoo_file);
  387. X#endif
  388. X   prterror ('m', "Archive time adjusted.\n");
  389. X   zooexit (0);
  390. X}
  391. X
  392. X/* make list of files, excluding archive and its backup */
  393. Xlongest = LONGEST;
  394. Xif (!inargs) {
  395. X   makelist(argc, argv, flist, MAXADD-2, zoo_fname, zoo_bak, ".", &longest);
  396. X   /*                                    ^^         ^^       ^^ exclude */
  397. X}
  398. X
  399. Xfptr = 0;    /* ready to get filename (if makelist() was called) or to
  400. X                    begin adding filenames (if reading them from stdin) */
  401. X
  402. Xwhile (1) {
  403. X   unsigned int this_date, this_time;
  404. X   int INLIST; /* boolean */
  405. X   int RECENT; /* boolean */
  406. X   int danger; /* if update requested and disk copy is out of date */
  407. X    if (inargs) {
  408. X    again: /* loop back if filename was same as archive name or its backup */
  409. X        this_path = getstdin();            /* pathname from stdin, in static area */
  410. X        if (this_path != NULL) {
  411. X            if (samefile (nameptr(zoo_fname),nameptr(this_path)) ||
  412. X                        samefile (nameptr(zoo_bak),nameptr(this_path)))
  413. X                goto again;                 /* don't add archive to itself */
  414. X            modpath (this_path);
  415. X        /* if moving files, add to list for later deletion;  if list overflows,
  416. X            terminate addition loop and give warning message */
  417. X            if (move) {
  418. X                if (fptr >= MAXADD-2) {
  419. X                    prterror ('w', too_many_files, MAXADD-2);
  420. X                    this_path = NULL;
  421. X                } else
  422. X                    flist[fptr++] = strdup (this_path);
  423. X            }
  424. X        }
  425. X    } else  {
  426. X        this_path = flist[fptr++];
  427. X    }
  428. X    /* exit the addition loop when no more pathnames are left */
  429. X    if (this_path == NULL) {
  430. X        /* in case stdin was being read, make sure flist is NULL-terminated */
  431. X        flist[fptr] = NULL;
  432. X        break;
  433. X    }
  434. X
  435. X   basename (this_path, this_fname);   /* get just filename for later */
  436. X
  437. X   this_file = zooopen(this_path, Z_READ);
  438. X   if (this_file == NOFILE) {
  439. X      prterror ('e', could_not_open, this_path);
  440. X      exit_status++;
  441. X      continue;
  442. X   }
  443. X
  444. X#ifndef PORTABLE
  445. X   /* Test to see if this is a Z format file.  We assume the file is Z format
  446. X      if (a) tag is correct and (b) type is 1 and (c) embedded filename
  447. X      is not longer than FNAMESIZE.  
  448. X   */
  449. X   if (z_fmt) {
  450. X      zooread (this_file, (char *) &tiny_header, sizeof(tiny_header));
  451. X      if (tiny_header.tinytag == TINYTAG && tiny_header.type == 1 &&
  452. X                        strlen (tiny_header.fname) <= FNAMESIZE)
  453. X          /* ok */ ;
  454. X      else {
  455. X         zooclose (this_file);
  456. X         prterror ('e', "File %s does not have Z format.\n", this_fname);
  457. X         exit_status++;
  458. X         continue;
  459. X      }
  460. X   }
  461. X#endif
  462. X
  463. X   /* get file time;  also fix name */
  464. X#ifndef PORTABLE
  465. X   if (z_fmt) {
  466. X      direntry.date = tiny_header.date;
  467. X      direntry.time = tiny_header.time;
  468. X      strcpy (direntry.fname, tiny_header.fname);
  469. X      direntry.dirlen = direntry.namlen = 0;
  470. X   } else {
  471. X#endif
  472. X
  473. X      /* Get timstamp of file being added */
  474. X#ifdef GETUTIME
  475. X      getutime (this_path, &direntry.date, &direntry.time);
  476. X#else
  477. X      gettime (this_file, &direntry.date, &direntry.time);
  478. X#endif
  479. X
  480. X        /* save file attributes */
  481. X#ifdef FATTR
  482. X        /* we expect getfattr() to set all attr. bits;  currently
  483. X            only the portable format is recognized */
  484. X        {
  485. X# ifdef FATTR_FNAME
  486. X            unsigned long getfattr PARMS ((char *);
  487. X            direntry.fattr = getfattr (this_path);
  488. X# else
  489. X            unsigned long getfattr PARMS ((ZOOFILE));
  490. X            direntry.fattr = getfattr (this_file);
  491. X# endif /* FATTR_FNAME */
  492. X        }
  493. X#else
  494. X            direntry.fattr = NO_FATTR;    /* none */
  495. X#endif /* FATTR */
  496. X
  497. X#ifdef FOLD
  498. X      strlwr(this_fname);
  499. X#endif
  500. X      dosname (this_fname, direntry.fname);  /* MSDOS filename */
  501. X
  502. X   /*
  503. X   Store long filename into direntry.lfname iff it is different from MSDOS
  504. X   filename.  Also store directory name if need_dir is true.  Moved out of 
  505. X   zooadd() so zooadd() doesn't get too big for optimization.
  506. X   */
  507. X   storefname (&direntry, this_path, need_dir);
  508. X
  509. X#ifndef PORTABLE
  510. X   }
  511. X#endif
  512. X
  513. X#ifdef DEBUG
  514. Xprintf ("zooadd:  direntry.lfname = [%s]  direntry.dirname = [%s]\n",
  515. X                  direntry.lfname, direntry.dirname);
  516. X#endif
  517. X
  518. X   /* if update option, then we add file if it is already in the archive 
  519. X      AND the archived file is older */
  520. X
  521. X   /* The following logic was derived from a Karnaugh map so it may
  522. X      be hard to understand.  Essentially, if U=update requested,
  523. X      N=new files requested, I=file is already in archive, and
  524. X      R=file being archived is more recent than file already in
  525. X      archive, then the boolean equation is:
  526. X
  527. X      add = U' (N' + I') + U (IR  + I'N)
  528. X   */
  529. X
  530. X   /* Get the filename to use for this addition.  */
  531. X   whichname = choosefname(&direntry);
  532. X
  533. X   /* Get position in archive of any old file of same name, ignoring
  534. X        any directory prefix if need_dir is not true.  Also get its
  535. X        date, time, version flag, and version number. */
  536. X   prev_pos = inlist (fullpath (&direntry), &this_date, &this_time, 
  537. X                &this_version_no, &high_vflag, &high_version_no, 
  538. X                &high_pos, !need_dir);
  539. X
  540. X/* define DBG_INLIST for debugging by printing values returned by inlist() */
  541. X#ifdef DBG_INLIST
  542. X    printf ("FROM inlist(): prev_pos=%ld, high_pos=%ld\n", prev_pos, high_pos);
  543. X    printf ("this_version_no=%u, high_vflag=%4x, high_version_no=%u\n",
  544. X                this_version_no,    high_vflag,     high_version_no);
  545. X#endif
  546. X
  547. X   INLIST = prev_pos > 0;  /* already in archive if positive value */
  548. X   if (INLIST) {
  549. X      int result;
  550. X      result = cmpnum (direntry.date, direntry.time, this_date, this_time);
  551. X      RECENT = result > 0;
  552. X      danger = result < 0;
  553. X   } else
  554. X      danger = 0; /* And RECENT is undefined and should not be used */
  555. X
  556. X   if (
  557. X         !update && (!new || !INLIST) ||
  558. X         update && (INLIST && RECENT || !INLIST && new)
  559. X      )
  560. X         ;  /* then continue and add file */
  561. X   else {
  562. X      if (update && danger)
  563. X         prterror ('w', "Archived copy of %s is newer.\n", whichname);
  564. X      zooclose (this_file);
  565. X      continue;   /* cycle back, skip this file */
  566. X   }
  567. X
  568. X#ifdef CHEKDIR
  569. X   /* Don't add if this is a directory */
  570. X   if (isadir (this_file)) {
  571. X      zooclose (this_file);
  572. X      continue;
  573. X   }
  574. X#else
  575. X# ifdef CHEKUDIR
  576. X   /* Don't add if this is a directory */
  577. X   if (isuadir (this_path)) {
  578. X      zooclose (this_file);
  579. X      continue;
  580. X   }
  581. X# endif /* CHEKUDIR */
  582. X#endif /* CHEKDIR */
  583. X
  584. X   /* Create directory entry for new file (but don't add just yet) */
  585. X   /* NOTE:  we already got file date and time above for update option */
  586. X    /* add tag, type, timezone, struc, system_id, and var_dir_len */
  587. X    newdir (&direntry);
  588. X
  589. X    if (!genson && zoo_status == NEW_ZOO || 
  590. X                (zoo_header.vdata & VFL_ON) == 0) {
  591. X        direntry.vflag = 0;
  592. X        direntry.version_no = 0;
  593. X    }
  594. X
  595. X   /* 
  596. X   Write a null direntry entry.  Thus, if an error occurs or the program
  597. X   is interrupted, the end of the archive will still be meaningful.
  598. X   Special check needed for first one written.
  599. X   */
  600. X
  601. X   direntry.next = direntry.offset = 0L;     /* trailing null entry */
  602. X   this_dir_offset = zootell (zoo_file);
  603. X   if (!firstfile) {
  604. X      writedir (&direntry, zoo_file);
  605. X   } else {
  606. X      /*
  607. X      Before adding the first file to the archive, we must make sure that
  608. X      the previous directory chain (if any) is properly terminated with a
  609. X      null entry of the right size.  If this is a new archive, we simply
  610. X      write a new null entry of the right size.  If this is an existing
  611. X      archive, we must check the size of the previous trailing null entry. 
  612. X      If it is too small, we will back up to the most recent real directory
  613. X      entry and change its .next field to point to end of file.  
  614. X      */
  615. X
  616. X      if (zoo_status == NEW_ZOO) {
  617. X         writedir (&direntry, zoo_file);        /* write null dir entry */
  618. X      } else {
  619. X         struct direntry tmpentry;
  620. X         long tmppos;
  621. X         int oldlen, newlen;
  622. X         tmppos = zootell (zoo_file);
  623. X         frd_dir (&tmpentry, zoo_file);
  624. X#define  DIRLEN(x)   ((x.type<2) ? SIZ_DIR : (SIZ_DIRL+x.var_dir_len))
  625. X         oldlen = DIRLEN(tmpentry);             /* get length of direntry */
  626. X         newlen = DIRLEN(direntry);             /* ditto */
  627. X
  628. X         if (newlen > oldlen) {                 /* trouble */
  629. X            zooseek (zoo_file, last_old, 0);    /* back to previous entry */
  630. X            frd_dir (&tmpentry, zoo_file);
  631. X            zooseek (zoo_file, 0L, 2);          /* get EOF position */
  632. X            tmpentry.next = zootell (zoo_file);    /* point to EOF */
  633. X            zooseek (zoo_file, last_old, 0);    /* back to previous entry */
  634. X            writedir (&tmpentry, zoo_file);     /* update it */
  635. X            zooseek (zoo_file, 0L, 2);          /* to EOF ... */
  636. X            this_dir_offset = zootell (zoo_file);
  637. X            writedir (&direntry, zoo_file);     /* ...write null dir entry */
  638. X         } else
  639. X            zooseek (zoo_file, tmppos, 0);      /* long enough -- let it be */
  640. X      } /* if (zoo_status == NEW_ZOO) ... */
  641. X   } /* if (!firstfile) ... */
  642. X
  643. X   /* Now `this_dir_offset' is where the next directory entry will go */
  644. X
  645. X   /* first file added goes at EOF to avoid overwriting comments */
  646. X   if (firstfile) {
  647. X      zooseek (zoo_file, 0L, 2);                   /* EOF */
  648. X      direntry.offset = zootell (zoo_file) + SIZ_FLDR;
  649. X   } else {
  650. X      direntry.offset = this_dir_offset + SIZ_DIRL + 
  651. X         direntry.var_dir_len + SIZ_FLDR;
  652. X   }
  653. X
  654. X   direntry.major_ver = MAJOR_EXT_VER;    /* minimum version number needed */
  655. X   direntry.minor_ver = MINOR_EXT_VER;    /* .. to extract */
  656. X   direntry.deleted = 0;               /* not deleted, naturally */
  657. X   direntry.comment = 0L;              /* no comment (yet) */
  658. X   direntry.cmt_size = 0;          /* .. so no size either */
  659. X
  660. X   save_position = direntry.offset;          /* save position in case of error */
  661. X
  662. X   zooseek (zoo_file, direntry.offset - SIZ_FLDR, 0);
  663. X   zoowrite (zoo_file, file_leader, SIZ_FLDR);
  664. X
  665. X#ifdef PORTABLE
  666. X   prterror ('m', "%-*s -- ", longest, this_path);
  667. X#else
  668. X   if (z_fmt)
  669. X      prterror ('m', "%-12s <== %-*s -- ", 
  670. X         direntry.fname, longest, this_path);
  671. X   else
  672. X      prterror ('m', "%-*s -- ", longest, this_path);
  673. X
  674. X#endif /* PORTABLE */
  675. X
  676. X   crccode = 0;
  677. X#ifndef PORTABLE
  678. X   if (z_fmt) 
  679. X    {
  680. X      direntry.packing_method = tiny_header.packing_method;
  681. X      zooseek (this_file, (long) (sizeof(tiny_header)+tiny_header.cmt_size), 0);
  682. X      status = getfile (this_file, zoo_file, tiny_header.size_now, 1);
  683. X   } else 
  684. X#endif
  685. X    if (suppress) {                    /* suppress compression */
  686. X      direntry.packing_method = 0;           /* no compression */
  687. X      status = getfile (this_file, zoo_file, -1L, 1);
  688. X   } else {
  689. X#ifdef UNBUF_IO    /* unbuffered I/O */
  690. X        long lseek PARMS ((int, long, int));
  691. X        long tell PARMS ((int));
  692. X        int this_fd, zoo_fd;
  693. X#endif
  694. X      direntry.packing_method = 1;                   /* compressed */
  695. X#ifdef UNBUF_IO
  696. X        this_fd = fileno (this_file);                        /* get ..                    */
  697. X        zoo_fd = fileno (zoo_file);                        /* ... file descriptors    */
  698. X        zooseek (zoo_file, zootell (zoo_file), 0);    /* synch */
  699. X        zooseek (this_file, zootell (this_file), 0);    /* synch */
  700. X      status = lzc(this_fd, zoo_fd);                    /* add with compression */
  701. X        zooseek (zoo_file, tell (zoo_fd), 0);            /* resynch    */
  702. X        zooseek (this_file, tell (this_fd), 0);        /* resynch    */
  703. X#else
  704. X      status = lzc(this_file, zoo_file);            /* add with compression */
  705. X#endif /* UNBUF_IO */
  706. X
  707. X   }
  708. X   if (status != 0) { /* if I */
  709. X      ++exit_status;                         /* remember error */
  710. X      if (status == 1)
  711. X         prterror ('F', no_memory);
  712. X      else if (status == 2)
  713. X         prterror ('F', disk_full);
  714. X      else if (status == 3)
  715. X         prterror ('F', "Read error.\n");
  716. X      else
  717. X         prterror ('F', internal_error);
  718. X      success = 0;
  719. X   } else {
  720. X      direntry.next  = zootell (zoo_file);
  721. X      direntry.size_now = direntry.next - direntry.offset;
  722. X
  723. X      /* find and store original size of file just compressed */
  724. X/*DEBUG VMS*/ zooseek (this_file, 0L, 2);    /* seek to EOF */
  725. X
  726. X      direntry.org_size = zootell (this_file);  /* should be EOF already */
  727. X
  728. X      /* If the compressed one is bigger, just copy */
  729. X
  730. X      if (direntry.size_now >= direntry.org_size &&   /* if II */
  731. X            direntry.packing_method != 0) {
  732. X         zooseek (zoo_file, save_position, 0);  /* ..restore file pointer */
  733. X         zootrunc (zoo_file);                   /* ..truncate file */
  734. X         direntry.packing_method = 0;           /* ..and just copy */
  735. X         zooseek (this_file, 0L, 0);            /* (but rewind first!) */
  736. X         crccode = 0;                           /* re-start crc from 0 */
  737. X         status = getfile (this_file, zoo_file, -1L, 1);
  738. X         if (status != 0) {  /* if III */
  739. X            success = 0;
  740. X            printf (disk_full);
  741. X            exit_status++;
  742. X         } else {
  743. X            success = 1;
  744. X            direntry.next  = zootell (zoo_file);
  745. X            direntry.size_now = direntry.next - direntry.offset;
  746. X         } /* end if III */
  747. X      } else {
  748. X         success = 1;
  749. X      } /* end if II */
  750. X
  751. X   } /* end if I */
  752. X
  753. X   if (success) {                               /* file successfully added */
  754. X      addcount++;                               /* how many added */
  755. X      direntry.file_crc = crccode;
  756. X
  757. X      /* remember most recent date and time */
  758. X      if (cmpnum (direntry.date,direntry.time,latest_date,latest_time) > 0) {
  759. X            latest_date = direntry.date;
  760. X            latest_time = direntry.time;
  761. X      }
  762. X
  763. X#if 0
  764. X      /* mark any previous version of this file in archive as deleted */
  765. X      dir2entry.comment = 0L;       /* for later use assigning to direntry */
  766. X      dir2entry.cmt_size = 0;
  767. X#endif
  768. X
  769. X      if (!z_fmt)
  770. X         prterror ('M', " (%2d%%) ", cfactor (direntry.org_size, direntry.size_now));
  771. X
  772. X        oldcmtsiz = 0;                                /* assume no old comment */
  773. X        oldcmtpos = 0L;
  774. X
  775. X      if (prev_pos > 0) {                                        /* in archive */
  776. X            int delold = 0;                                        /* delete old? */
  777. X            /* if versions active both archive-wide and for file */
  778. X            if ((zoo_header.vdata & VFL_ON) && (high_vflag & VFL_ON)) {
  779. X                /* next test is optimization, to avoid redundant I/O */
  780. X                if (high_pos != prev_pos || this_version_no == 1) {
  781. X                    /* prev highest is no longer highest so adjust vflag */
  782. X                    long save_pos = zootell (zoo_file);            /*DEBUG*/
  783. X                    zooseek (zoo_file, high_pos, 0);
  784. X                    readdir (&dir2entry, zoo_file, 1);
  785. X                    oldcmtpos = dir2entry.comment;
  786. X                    oldcmtsiz = dir2entry.cmt_size;
  787. X                    dir2entry.vflag &= (~VFL_LAST);                /* no longer highest */
  788. X                    zooseek (zoo_file, high_pos, 0);
  789. X                    writedir (&dir2entry, zoo_file);
  790. X                    zooseek (zoo_file, save_pos, 0);                /*DEBUG*/
  791. X                }
  792. X
  793. X                direntry.version_no = high_version_no + 1; /* ..one higher */
  794. X                direntry.vflag = high_vflag;
  795. X                /* now see if we need to delete older version */
  796. X                fgens = high_vflag & VFL_GEN;
  797. X                if (fgens == 0)
  798. X                    fgens = zgens;
  799. X                if (zgens != 0 && zgens < fgens)
  800. X                    fgens = zgens;
  801. X                if (fgens != 0 && direntry.version_no - this_version_no >= fgens) {
  802. X                    delold = 1;
  803. X                    prterror ('M', "replaced+\n");
  804. X                } else
  805. X                    prterror ('M', "added+\n");
  806. X            } else {
  807. X                prterror ('M', "replaced\n");
  808. X                delold = 1;
  809. X            }
  810. X
  811. X            if (delold) {                                            /* deleting old file */
  812. X                long save_pos = zootell (zoo_file);            /*DEBUG*/
  813. X                ++delcount;                                            /* remember to pack */
  814. X                zooseek (zoo_file, prev_pos, 0);
  815. X                readdir (&dir2entry, zoo_file, 1);
  816. X                if (dir2entry.cmt_size != 0) {        /* propagate latest comment */
  817. X                    oldcmtpos = dir2entry.comment;
  818. X                    oldcmtsiz = dir2entry.cmt_size;
  819. X                }
  820. X                dir2entry.deleted = 1;                            /* mark as deleted */
  821. X                /* following line is optimization if only 1 generation */
  822. X                dir2entry.vflag &= (~VFL_LAST);                /* no longer highest */
  823. X                zooseek (zoo_file, prev_pos, 0);
  824. X                writedir (&dir2entry, zoo_file);
  825. X                zooseek (zoo_file, save_pos, 0);                /*DEBUG*/
  826. X            }
  827. X      } else                                                         /* not in archive */
  828. X            prterror ('M', "added\n");
  829. X
  830. X      /* Preserve any old comment if we replaced or superseded the file */
  831. X      direntry.comment = oldcmtpos;
  832. X      direntry.cmt_size = oldcmtsiz;
  833. X
  834. X#ifndef PORTABLE
  835. X      /* Copy comment if any from Z format file */
  836. X      if (z_fmt && tiny_header.cmt_size != 0) {
  837. X         zooseek (this_file, (long) sizeof(tiny_header), 0); /* to comment */
  838. X         direntry.comment = zootell (zoo_file);
  839. X         direntry.cmt_size = tiny_header.cmt_size;
  840. X         /* 4th param is 0 for no CRC */
  841. X         getfile (this_file, zoo_file, (long) tiny_header.cmt_size, 0);
  842. X         direntry.next = zootell (zoo_file);
  843. X      } 
  844. X#endif
  845. X
  846. X      /* if user requested comments, any previous comment in a Z format
  847. X         file may now be manually overwritten */
  848. X      if (add_comment && !feof (stdin)) {
  849. X         show_comment (&direntry, zoo_file, 1, whichname);
  850. X         get_comment (&direntry, zoo_file, this_path);
  851. X         direntry.next = zootell (zoo_file);    /* update .next ptr */
  852. X      } /* end if */
  853. X
  854. X#ifndef PORTABLE
  855. X      /* if adding Z format archive, copy relevant fields from its header */
  856. X      if (z_fmt) {   /* moved out to shorten code & allow optimizer to work */
  857. X         copyfields (&direntry, &tiny_header);
  858. X      }
  859. X#endif
  860. X
  861. X      debug((printf ("zooadd:  our new .next = [%lx].\n", direntry.next)))
  862. X
  863. X      {
  864. X         long savepos = zootell (zoo_file);    /* save position */
  865. X         zooseek (zoo_file, this_dir_offset, 0);
  866. X         writedir (&direntry, zoo_file);
  867. X         zooseek (zoo_file, savepos, 0);    /* restore position */
  868. X      }
  869. X
  870. X   } else {                               /* file was not properly added */
  871. X      zooseek (zoo_file, save_position, 0);  /* ..restore file pointer */
  872. X      zootrunc (zoo_file);                   /* ..truncate file */
  873. X   } /* end if */
  874. X   zooclose (this_file);
  875. Xif (!success)
  876. X   break;
  877. Xfirstfile = 0;
  878. X} /* end for */
  879. X
  880. Xsave_position = zootell (zoo_file);
  881. X
  882. X/* Write a null direntry entry */
  883. Xzooseek (zoo_file, save_position, 0);
  884. Xwritenull (zoo_file, MAXDIRSIZE);
  885. Xzootrunc (zoo_file);  /* truncate */
  886. X
  887. X#ifdef NIXTIME
  888. Xzooclose (zoo_file);
  889. Xsetutime (zoo_path, latest_date, latest_time);
  890. X#else
  891. Xsettime (zoo_file, latest_date, latest_time);
  892. Xzooclose (zoo_file);
  893. X#endif
  894. X
  895. Xif (!addcount) {                    /* no files added */
  896. X   prterror ('m', "No files added.\n");
  897. X   if (zoo_status == NEW_ZOO)
  898. X      unlink (zoo_path);
  899. X} else {
  900. X   if (delcount && pack) { /* pack if user asked and found deleted entries */
  901. X      prterror ('M', "-----\nPacking...");
  902. X      zoopack (zoo_path, "PP");
  903. X      prterror ('M', "done\n");
  904. X   }
  905. X
  906. X   /* If files to move & we added some and no error so far, delete originals */
  907. X   if (move && !exit_status)
  908. X      if (kill_files (flist, longest) != 0)
  909. X         exit_status++;
  910. X}
  911. X
  912. Xif (exit_status)
  913. X   zooexit (1);
  914. X} /* end zoo_add */
  915. END_OF_FILE
  916. if test 25720 -ne `wc -c <'zooadd.c'`; then
  917.     echo shar: \"'zooadd.c'\" unpacked with wrong size!
  918. fi
  919. # end of 'zooadd.c'
  920. fi
  921. if test -f 'zoodel.c' -a "${1}" != "-c" ; then 
  922.   echo shar: Will not clobber existing file \"'zoodel.c'\"
  923. else
  924. echo shar: Extracting \"'zoodel.c'\" \(9557 characters\)
  925. sed "s/^X//" >'zoodel.c' <<'END_OF_FILE'
  926. X#ifndef LINT
  927. X/* @(#) zoodel.c 2.19 88/02/06 21:23:36 */
  928. Xstatic char sccsid[]="@(#) zoodel.c 2.19 88/02/06 21:23:36";
  929. X#endif /* LINT */
  930. X
  931. X/*
  932. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  933. X(C) Copyright 1988 Rahul Dhesi -- All rights reserved
  934. X*/
  935. X#include "options.h"
  936. X/* Deletes or undeletes entries from an archive.  choice=1 requests
  937. X   deletion and choice=0 requests undeletion. */
  938. X#include "portable.h"
  939. X#ifndef    OK_STDIO
  940. X#include <stdio.h>
  941. X#define    OK_STDIO
  942. X#endif
  943. X#include "various.h" /* may not be needed */
  944. X#include "zooio.h"
  945. X#include "zoo.h"
  946. X#include "zoofns.h"
  947. X#include "errors.i"
  948. X
  949. X#ifndef NOSIGNAL
  950. X#include <signal.h>
  951. X#endif
  952. X
  953. X#ifdef LINT_ARGS
  954. Xint needed (char *, struct direntry *, struct zoo_header *);
  955. Xint ver_too_high (struct zoo_header *);
  956. X#else
  957. Xint needed ();
  958. Xint ver_too_high ();
  959. X#endif
  960. X
  961. Xextern int quiet;
  962. X
  963. Xvoid zoodel (zoo_path, option, choice)
  964. Xchar *zoo_path;
  965. Xchar *option;
  966. Xint choice;
  967. X{
  968. X#ifndef NOSIGNAL
  969. X   int (*oldsignal)();        /* to save previous SIGINT handler */
  970. X#endif
  971. X   int delcount = 0;          /* how many entries we [un]deleted */
  972. X   char matchname[PATHSIZE];  /* will hold full pathname */
  973. X   register ZOOFILE zoo_file;
  974. X   struct zoo_header zoo_header;
  975. X   struct direntry direntry;
  976. X   unsigned int latest_date = 0;      /* so we can set time of archive later */
  977. X   unsigned int latest_time = 0;
  978. X   int pack = 0;              /* pack after deletion? */
  979. X   int file_deleted = 0;      /* any files deleted? */
  980. X   int one = 0;               /* del/undel one file only */
  981. X   int done;                  /* loop control */
  982. X    int action;                        /* delete/undelete or adjust generation */
  983. X    int subopt;                        /* sub option to action */
  984. X    long gencount;                    /* generation count */
  985. X    int doarchive = 0;            /* whether to adjust archive gen count */
  986. X    unsigned valtoshow;            /* value to show in informative message */
  987. X    int dodel = 0;                    /* selection of deleted files */
  988. X    int selected;                    /* if current direntry selected */
  989. X
  990. X/* values for action */
  991. X#define NO_ACTION    0    /* nothing */
  992. X#define DEL_UNDEL    1    /* delete or undelete file */
  993. X#define ADJ_LIM    2    /* adjust generation limit */
  994. X#define ADJ_GCNT    3    /* adjust generation count */
  995. X#define GEN_ON        4    /* turn on generations */
  996. X#define GEN_OFF        5    /* turn off generations */
  997. X
  998. X/* values for subopt */
  999. X#define    SET        0
  1000. X#define    INC        1
  1001. X
  1002. Xaction = NO_ACTION;
  1003. Xif (*option == 'g') {
  1004. X    while (*(++option)) {
  1005. X        switch (*option) {
  1006. X            case 'A': doarchive = 1; break;
  1007. X            case 'q': quiet++; break;
  1008. X            case 'l': action = ADJ_LIM; break;
  1009. X            case 'c': action = ADJ_GCNT; break;
  1010. X            case '=':
  1011. X                subopt = SET; gencount = calc_ofs (++option);
  1012. X                if (action == ADJ_GCNT && gencount == 0)
  1013. X                    prterror ('f', "Generation count must be nonzero.\n");
  1014. X                goto opts_done;
  1015. X            case '+':
  1016. X                if (action == NO_ACTION) {
  1017. X                    if (option[1] =='\0') {
  1018. X                        action = GEN_ON;
  1019. X                        goto opts_done;
  1020. X                    } else
  1021. X                        prterror ('f', garbled);
  1022. X                } else {
  1023. X                    subopt = INC; gencount = calc_ofs (++option);
  1024. X                    goto opts_done;
  1025. X                }
  1026. X            case '-':
  1027. X                if (action == NO_ACTION) {
  1028. X                    if (option[1] =='\0') {
  1029. X                        action = GEN_OFF;
  1030. X                        goto opts_done;
  1031. X                    } else
  1032. X                        prterror ('f', garbled);
  1033. X                } else {
  1034. X                    subopt = INC; gencount = - calc_ofs (++option);
  1035. X                    goto opts_done;
  1036. X                }
  1037. X            case 'd':
  1038. X                dodel++; break;
  1039. X            default:
  1040. X                prterror ('f', garbled);
  1041. X        } /* end switch */
  1042. X    } /* end while */
  1043. X    /* if normal exit from while loop, it means bad command string */
  1044. X    prterror ('f', garbled);
  1045. X    opts_done:                             /* jump here from exit in while loop above */
  1046. X        if (action == NO_ACTION)
  1047. X            prterror ('f', garbled);
  1048. X} else {
  1049. X    action = DEL_UNDEL;
  1050. X    while (*(++option)) {
  1051. X        switch (*option) {
  1052. X            case 'P': pack++; break;            /* pack after adding */
  1053. X            case 'q': quiet++; break;           /* be quiet */
  1054. X            case '1': one++; break;             /* del or undel only one file */
  1055. X            default:
  1056. X                prterror ('f', inv_option, *option);
  1057. X        }
  1058. X    } /* end while */
  1059. X}
  1060. X
  1061. X   /* Open archive for read/write/binary access.  It must already exist */
  1062. X   if ((zoo_file = zooopen (zoo_path, Z_RDWR)) == NOFILE) {
  1063. X      prterror ('f', could_not_open, zoo_path);
  1064. X   }
  1065. X   
  1066. X   /* read archive header */
  1067. X   frd_zooh (&zoo_header, zoo_file);
  1068. X   if ((zoo_header.zoo_start + zoo_header.zoo_minus) != 0L)
  1069. X      prterror ('f', failed_consistency);
  1070. X   if (ver_too_high (&zoo_header))
  1071. X      prterror ('f', wrong_version, zoo_header.major_ver, zoo_header.minor_ver);
  1072. X
  1073. X    if (doarchive) {                                    /* manipulate archive gen val */
  1074. X        unsigned zoo_date, zoo_time;
  1075. X#ifdef GETUTIME
  1076. X        getutime (zoo_path, &zoo_date, &zoo_time);    /* save archive timestamp */
  1077. X#else
  1078. X        gettime (zoo_file, &zoo_date, &zoo_time);
  1079. X#endif
  1080. X        if (zoo_header.type == 0)
  1081. X            prterror ('f', packfirst);
  1082. X        if (action == ADJ_LIM)    {
  1083. X            unsigned newgencount;    
  1084. X            if (subopt == SET)
  1085. X                newgencount = (unsigned) gencount;
  1086. X            else                                                                        /* INC */
  1087. X                newgencount = (zoo_header.vdata & VFL_GEN) + (unsigned) gencount;
  1088. X            newgencount &= VFL_GEN;            /* reduce to allowed bits */
  1089. X            zoo_header.vdata &= (~VFL_GEN);
  1090. X            zoo_header.vdata |= newgencount;
  1091. X            prterror ('M', "Archive generation limit is now %u\n", newgencount);
  1092. X        } else if (action == GEN_ON) {
  1093. X            zoo_header.vdata |= VFL_ON;
  1094. X            prterror ('M', "Archive generations on\n");
  1095. X        } else if (action == GEN_OFF) {
  1096. X            zoo_header.vdata &= (~VFL_ON);
  1097. X            prterror ('M', "Archive generations off\n");
  1098. X        } else 
  1099. X            prterror ('f', garbled);
  1100. X        zooseek (zoo_file, 0L, 0);        /* back to begining of file */
  1101. X        fwr_zooh (&zoo_header, zoo_file);
  1102. X#ifdef NIXTIME
  1103. X        zooclose (zoo_file);
  1104. X        setutime (zoo_path, zoo_date, zoo_time);    /* restore archive timestamp */
  1105. X#else
  1106. X        settime (zoo_file, zoo_date, zoo_time);
  1107. X        zooclose (zoo_file);
  1108. X#endif
  1109. X        return;
  1110. X    }
  1111. X
  1112. X   zooseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */
  1113. X
  1114. X   done = 0;            /* loop not done yet */
  1115. X   while (1) {
  1116. X      long this_dir_offset;
  1117. X      this_dir_offset = zootell (zoo_file);   /* save pos'n of this dir entry */
  1118. X      frd_dir (&direntry, zoo_file);
  1119. X      if (direntry.zoo_tag != ZOO_TAG) {
  1120. X         prterror ('f', bad_directory);
  1121. X      }
  1122. X      if (direntry.next == 0L) {                /* END OF CHAIN */
  1123. X         break;                                 /* EXIT on end of chain */
  1124. X      }
  1125. X
  1126. X        /* select directory entry if it matches criteria */
  1127. X        selected = (
  1128. X                          (action == DEL_UNDEL && direntry.deleted != choice)
  1129. X                  ||
  1130. X                          (action != DEL_UNDEL &&
  1131. X                         (dodel && direntry.deleted ||
  1132. X                                (dodel < 2 && !direntry.deleted))
  1133. X                          )
  1134. X                      );
  1135. X
  1136. X        /* WARNING: convention of choice=1 for deleted entry must be same as
  1137. X        in direntry definition in zoo.h */
  1138. X    
  1139. X        /* Test for "done" so if "one" option requested, [un]del only 1 file */
  1140. X        /* But we go through the whole archive to adjust archive time */
  1141. X
  1142. X        strcpy (matchname, fullpath (&direntry));        /* get full pathname */
  1143. X        if (zoo_header.vdata & VFL_ON)
  1144. X            add_version (matchname, &direntry);            /* add version suffix */
  1145. X
  1146. X        if (!done && selected && needed(matchname, &direntry, &zoo_header)) {
  1147. X            prterror ('m', "%-14s -- ", matchname);
  1148. X            delcount++;
  1149. X            if (action == DEL_UNDEL) {
  1150. X                direntry.deleted = choice;
  1151. X                if (choice)
  1152. X                    file_deleted++;      /* remember if any files actually deleted */
  1153. X            } else {                            /* ADJ_LIM or ADJ_GENCNT */
  1154. X                if (direntry.vflag & VFL_ON) {        /* skip if no versions */
  1155. X                    if (action == ADJ_LIM) {
  1156. X                        unsigned newgencount;
  1157. X                        if (subopt == SET)
  1158. X                            newgencount = (unsigned) gencount;
  1159. X                        else                                                     /* INC */
  1160. X                            newgencount =
  1161. X                                (int) (direntry.vflag & VFL_GEN) + (int) gencount;
  1162. X                        newgencount &= VFL_GEN;
  1163. X                        direntry.vflag &= (~VFL_GEN);
  1164. X                        direntry.vflag |= newgencount;
  1165. X                        valtoshow = newgencount;
  1166. X                    } else {                                                    /* ADJ_GCNT */
  1167. X                        if (subopt == SET)
  1168. X                            direntry.version_no = (unsigned) gencount;
  1169. X                        else                                                     /* INC */
  1170. X                            direntry.version_no += (int) gencount;
  1171. X                        direntry.version_no &= VER_MASK; /* avoid extra bits */
  1172. X                        valtoshow = direntry.version_no;
  1173. X                    }
  1174. X                }
  1175. X            }
  1176. X
  1177. X            zooseek (zoo_file, this_dir_offset, 0);
  1178. X
  1179. X#ifndef NOSIGNAL
  1180. X            oldsignal = signal (SIGINT, SIG_IGN);  /* disable ^C for write */
  1181. X#endif
  1182. X            if (fwr_dir (&direntry, zoo_file) == -1)
  1183. X                prterror ('f', "Could not write to archive\n");
  1184. X#ifndef NOSIGNAL
  1185. X            signal (SIGINT, oldsignal);
  1186. X#endif
  1187. X            if (action == DEL_UNDEL)
  1188. X                prterror ('M', choice ? "deleted\n" : "undeleted\n");
  1189. X            else {
  1190. X                if (direntry.vflag & VFL_ON)
  1191. X                    prterror ('M', "adjusted to %u\n", valtoshow);
  1192. X                else
  1193. X                    prterror ('M', "no generations\n");
  1194. X            }
  1195. X            if (one)
  1196. X                done = 1;            /* if 1 option, done after 1 file */
  1197. X        }
  1198. X
  1199. X      /* remember most recent date and time if entry is not deleted */
  1200. X      if (!direntry.deleted)
  1201. X         if (direntry.date > latest_date ||
  1202. X            (direntry.date == latest_date && direntry.time > latest_time)) {
  1203. X               latest_date = direntry.date;
  1204. X               latest_time = direntry.time;
  1205. X         }
  1206. X      zooseek (zoo_file, direntry.next, 0); /* ..seek to next dir entry */
  1207. X   } /* endwhile */
  1208. X
  1209. X   if (!delcount)
  1210. X      printf ("Zoo:  No files matched.\n");
  1211. X   else {
  1212. X#ifdef NIXTIME
  1213. X      zooclose (zoo_file);
  1214. X      setutime (zoo_path, latest_date, latest_time);
  1215. X#else
  1216. X#if 0
  1217. X      fflush (zoo_file);         /* superstition:  might help time stamp */
  1218. X#endif
  1219. X      settime (zoo_file, latest_date, latest_time);
  1220. X#endif
  1221. X   }
  1222. X
  1223. X#ifndef NIXTIME
  1224. Xzooclose (zoo_file);
  1225. X#endif
  1226. X
  1227. Xif (file_deleted && pack) {   /* pack if files were deleted and user asked */
  1228. X   prterror ('M', "-----\nPacking...");
  1229. X   zoopack (zoo_path, "PP");
  1230. X   prterror ('M', "done\n");
  1231. X}
  1232. X
  1233. X}
  1234. END_OF_FILE
  1235. if test 9557 -ne `wc -c <'zoodel.c'`; then
  1236.     echo shar: \"'zoodel.c'\" unpacked with wrong size!
  1237. fi
  1238. # end of 'zoodel.c'
  1239. fi
  1240. echo shar: End of archive 9 \(of 10\).
  1241. cp /dev/null ark9isdone
  1242. MISSING=""
  1243. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  1244.     if test ! -f ark${I}isdone ; then
  1245.     MISSING="${MISSING} ${I}"
  1246.     fi
  1247. done
  1248. if test "${MISSING}" = "" ; then
  1249.     echo You have unpacked all 10 archives.
  1250.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1251. else
  1252.     echo You still need to unpack the following archives:
  1253.     echo "        " ${MISSING}
  1254. fi
  1255. ##  End of shell archive.
  1256. exit 0
  1257.